<?php
#
# dmBridge: a data access framework for CONTENTdm(R)
#
# Copyright © 2009, 2010, 2011 Board of Regents of the Nevada System of Higher
# Education, on behalf of the University of Nevada, Las Vegas
#

/**
 * <p>A class consisting of helper methods to assist in creating web page
 * templates. These methods are specific to search view and are neither
 * guaranteed nor expected to work in any other view.</p>
 *
 * <p>This class was called SearchDraw in dmBridge 1.x.</p>
 *
 * @author Alex Dolski <alex.dolski@unlv.edu>
 * @license http://www.opensource.org/licenses/mit-license.php
 */
class DMSearchTemplateHelper extends DMGenericTemplateHelper
implements DMTemplateHelper {

	public function helperWillRender() {
		$this->addStylesheetTag(
				dirname($_SERVER['PHP_SELF']) . "/includes/css/search_view.css");
		$this->addBodyScriptTag(
				"http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js");
		$this->addBodyScriptTag(
				dirname($_SERVER['PHP_SELF']) . "/includes/js/search_view.js");
	}

	/**
	 * @param get_parameters An array of HTTP GET key-value pairs to pass to
	 * the results page, e.g. "/objects?key=value"
	 * @since 0.3
	 */
	public function getHtmlDateSearch(array $get_parameters = array()) {
		$selected_year1 = $selected_year2 = $selected_month1 = $selected_month2
			= $selected_day1 = $selected_day2 = $earliest_year = $latest_year
			= $year1_options = $month1_options = $day1_options
			= $year2_options = $month2_options = $day2_options = $mode = $string
			= $field = $date_qualifier = null;
		$collection = $this->getView()->getCollection();
		$earliest_year = $collection->getDateSearchBeginYear();
		$latest_year = $collection->getDateSearchEndYear();

		// retrieve saved search input
		$input = DMHTTPRequest::getCurrent()->getSession()->getSearchInput();
		if ($input instanceof DMInput) {
			$date_qualifier = $input->getDateQualifier();
			if ($input->getPredicate(0) instanceof DMQueryPredicate) {
				if (!$input->getPredicate(0)->isProximity()) {
					$field = $input->getPredicate(0)->getField()->getNick();
					$mode = $input->getPredicate(0)->getMode();
					$string = $input->getPredicate(0)->getString();
				}
				if ($input->getBeginDate() instanceof DMDateTime) {
					$selected_year1 = $input->getBeginDate()->format('Y');
					$selected_month1 = $input->getBeginDate()->format('n');
					$selected_day1 = $input->getBeginDate()->format('j');
				}
				if ($input->getEndDate() instanceof DMDateTime) {
					$selected_year2 = $input->getEndDate()->format('Y');
					$selected_month2 = $input->getEndDate()->format('n');
					$selected_day2 = $input->getEndDate()->format('j');
				}
			}
		}
		$selected_year1 = ($selected_year1) ? $selected_year1 : $earliest_year;
		$selected_year2 = ($selected_year2) ? $selected_year2 : $latest_year;

		// assemble year1 <option> elements
		foreach (range($earliest_year, $latest_year, 1) as $y) {
			$year1_options .= sprintf('<option value="%d" %s>%d</option>',
				$y,
				($y == $selected_year1) ? 'selected="selected"' : '',
				$y
			);
		}

		// assemble month1 <option> elements
		foreach (range(1, 12) as $m) {
			$month1_options .= sprintf('<option value="%d" %s>%s</option>',
				$m,
				($m == $selected_month1) ? 'selected="selected"' : '',
				date('F', mktime(1, 1, 1, $m, 5))
			);
		}

		// assemble day1 <option> elements
		foreach (range(1, 31) as $d) {
			$day1_options .= sprintf('<option value="%d" %s>%d</option>',
				$d,
				($d == $selected_day1) ? 'selected="selected"' : '',
				$d
			);
		}

		// assemble year2 <option> elements
		foreach (range($earliest_year, $latest_year, 1) as $y) {
			$year2_options .= sprintf('<option value="%d" %s>%d</option>',
				$y,
				($y == $selected_year2) ? 'selected="selected"' : '',
				$y
			);
		}

		// assemble month2 <option> elements
		foreach (range(1, 12) as $m) {
			$month2_options .= sprintf('<option value="%d" %s>%s</option>',
				$m,
				($m == $selected_month2) ? 'selected="selected"' : '',
				date('F', mktime(1, 1, 1, $m, 5))
			);
		}

		// assemble day2 <option> elements
		foreach (range(1, 31) as $d) {
			$day2_options .= sprintf('<option value="%d" %s>%d</option>',
				$d,
				($d == $selected_day2) ? 'selected="selected"' : '',
				$d
			);
		}

		$alias = ($collection) ? $collection->getAlias() : "";

		return sprintf('<form method="get" action="%s" name="dmDateSearch">
				<fieldset id="dmDateSearch">
					<ol>
						<li class="dmTerms">
							<select name="CISOOP1">
								<option value="all" %s>All of the words</option>
								<option value="exact" %s>The exact phrase</option>
								<option value="any" %s>Any of the words</option>
								<option value="none" %s>None of the words</option>
							</select>

							<input type="search" size="30" name="CISOBOX1"
								value="%s" class="dmSearchField autofill"> in this field:

							<select id="dmDateSearchField" class="dmSearchFieldSelect" name="CISOFIELD1">
								%s
							</select>
						</li>

						<li id="dmDateSelect">
							<select id="dmDateQualifier" name="date_qualifier">
								<option value="from" %s>From</option>
								<option value="after" %s>After</option>
								<option value="before" %s>Before</option>
								<option value="on" %s>On</option>
							</select>
						</li>

						<li id="dmBeginDateSelect">
							<select name="y1" id="y1">%s</select>
							<select name="m1" id="m1">%s</select>
							<select name="d1" id="d1">%s</select>
						</li>

						<li id="dmEndDateSelect">
							<label id="dmEndDateLabel">To:</label>
							<select name="y2" id="y2">%s</select>
							<select name="m2" id="m2">%s</select>
							<select name="d2" id="d2">%s</select>
						</li>
					</ol>

					<div class="dmSearchCollectionList">
						<ul>%s</ul>
						%s
					</div>
					<p>
						%s
						%s
						<input type="submit" value="Search" class="dmSubmit">
					</p>
				</fieldset>
			</form>',
			DMInternalURI::getURIWithParams("objects" . $alias),
			($mode == 'all') ? 'selected="selected"' : '',
			($mode == 'exact') ? 'selected="selected"' : '',
			($mode == 'any') ? 'selected="selected"' : '',
			($mode == 'none') ? 'selected="selected"' : '',
			$string,
			$this->getFieldOptionElements($field),
			($date_qualifier == 'from') ? 'selected="selected"' : '',
			($date_qualifier == 'after') ? 'selected="selected"' : '',
			($date_qualifier == 'before') ? 'selected="selected"' : '',
			($date_qualifier == 'on') ? 'selected="selected"' : '',
			$year1_options, $month1_options, $day1_options,
			$year2_options, $month2_options, $day2_options,
			$this->getCollectionListElements(),
			$this->getCheckAllLinks(),
			$this->getHiddenCollectionElement(),
			$this->getHiddenElements($get_parameters)
		);
	}

	/**
	 * @param get_parameters An array of HTTP GET key-value pairs to pass to
	 * the results page, e.g. "/objects?key=value"
	 * @since 0.3
	 */
	public function getHtmlFieldSearch(array $get_parameters = array()) {
		$input = DMHTTPRequest::getCurrent()->getSession()->getSearchInput();
		$collection = $this->getView()->getCollection();

		$fields = array();
		$modes = array();
		$strings = array();
		$field_lis = "";
		for ($i = 0; $i < 3; $i++) {
			if ($input instanceof DMInput) {
				$term = $input->getPredicate($i);
				if ($term instanceof DMQueryPredicate) {
					if (!$term->isDate() && !$term->isProximity()) {
						$fields[$i] = $term->getField()->getNick();
						$modes[$i] = $term->getMode();
						$strings[$i] = $term->getString();
					}
				}
			}
			
			$field_lis .= sprintf(
				'<li>
					<select name="CISOOP%d">
						<option value="all" %s>All of the words</option>
						<option value="exact" %s>The exact phrase</option>
						<option value="any" %s>Any of the words</option>
						<option value="none" %s>None of the words</option>
					</select>
					<input type="search" size="30" name="CISOBOX%d" id="dmFieldSearchTextBox%d"
						value="%s" class="dmSearchField autofill"> in this field:
					<select name="CISOFIELD%d" id="dmSearchField%d" class="dmSearchFieldSelect">
						<option value="any">Any Field</option>
						%s
					</select>
				</li>',
				$i+1,
				(array_key_exists($i, $modes) && $modes[$i] == 'all') ? 'selected="selected"' : '',
				(array_key_exists($i, $modes) && $modes[$i] == 'exact') ? 'selected="selected"' : '',
				(array_key_exists($i, $modes) && $modes[$i] == 'any') ? 'selected="selected"' : '',
				(array_key_exists($i, $modes) && $modes[$i] == 'none') ? 'selected="selected"' : '',
				$i+1,
				$i,
				(array_key_exists($i, $strings)) ? DMString::websafe($strings[$i]) : '',
				$i+1,
				$i,
				(array_key_exists($i, $fields))
					? $this->getFieldOptionElements($fields[$i])
					: $this->getFieldOptionElements()
			);
		}

		$alias = ($collection) ? $collection->getAlias() : "";

		return sprintf('<input class="dmBridgeBaseURI" type="hidden" name="dmBridgeBaseURI" value="%s">
				<input class="dmBridgeSelectedCollection" type="hidden" name="selectedCollection" value="%s">
				<form method="get" action="%s" name="dmFieldSearch">
				<fieldset id="dmTermSearch">
					<ol>%s</ol>
					<div class="dmSearchCollectionList">
						<ul>%s</ul>
						%s
					</div>
					<p>
						%s
						%s
						<input type="submit" value="Search" class="dmSubmit">
					</p>
				</fieldset>
			</form>',
			DMConfigIni::getInstance()->getString("dmbridge.base_uri_path"),
			$this->getView()->getCollection()->getAlias(),
			DMInternalURI::getURIWithParams("objects" . $alias),
			$field_lis,
			$this->getCollectionListElements(),
			$this->getCheckAllLinks(),
			$this->getHiddenCollectionElement(),
			$this->getHiddenElements($get_parameters)
		);
	}

	/**
	 * @param get_parameters An array of HTTP GET key-value pairs to pass to
	 * the results page, e.g. "/objects?key=value"
	 * @since 0.3
	 */
	public function getHtmlProximitySearch(array $get_parameters = array()) {
		$collection = $this->getView()->getCollection();
		$strings = $nick = null;
		// retrieve saved search input
		$input = DMHTTPRequest::getCurrent()->getSession()->getSearchInput();
		if ($input instanceof DMInput) {
			$term0 = $input->getPredicate(0);
			$term1 = $input->getPredicate(1);
			if ($term0 instanceof DMQueryPredicate) {
				if (!$term0->isDate()) {
					$strings = array();
					$field = $term0->getField();
					$nick = $field->getNick();
					$strings[0] = $term0->getString();
					if ($term1 instanceof DMQueryPredicate) {
						if (!$term1->isDate()) {
							$strings[1] = $term1->getString();
						}
					}
				}
			}
		}

		$alias = ($collection) ? $collection->getAlias() : "";

		return sprintf(
			'<form method="get" action="%s" name="dmProximitySearch">
				<fieldset id="dmProximitySearch">
					<ol>
						<li>
							<label for="dmProximityString0">The word:</label>
							<input id="dmProximityString0" type="search" size="30"
								name="CISOBOX1" value="%s"
								class="dmSearchField autofill">
						</li>
						<li>
							<label for="dmProximity">Within</label>
							<select name="proximity" id="dmProximity">
								<option value="2">2</option>
								<option value="3">3</option>
								<option value="4">4</option>
								<option value="5">5</option>
								<option value="10">10</option>
								<option value="20">20</option>
								<option value="50">50</option>
								<option value="100">100</option>
							</select>

							<label for="dmProximityString1">words of:</label>
							<input id="dmProximityString1" type="search" size="30"
								name="CISOBOX2" value="%s"
								class="dmSearchField autofill">
						</li>
						<li>
							<label for="dmProximityField">In this field:</label>
							<select name="CISOFIELD1" id="dmProximityField" class="dmSearchFieldSelect">
								<option value="any">Any Field</option>
								%s
							</select>
						</li>
					</ol>

					<div class="dmSearchCollectionList">
						<ul>%s</ul>
						%s
					</div>
					<p>
						<input type="hidden" name="CISOOP1" value="exact">
						<input type="hidden" name="CISOOP2" value="exact">
						%s
						%s
						<input type="submit" value="Search" class="dmSubmit">
					</p>
				</fieldset>
			</form>',
			DMInternalURI::getURIWithParams("objects" . $alias),
			(count($strings)) ? DMString::websafe($strings[0]) : "",
			(count($strings) > 1) ? DMString::websafe($strings[1]) : "",
			$this->getFieldOptionElements($nick),
			$this->getCollectionListElements(),
			$this->getCheckAllLinks(),
			$this->getHiddenCollectionElement(),
			$this->getHiddenElements($get_parameters)
		);
	}

	private function getCheckAllLinks() {
		$tpl_set = $this->getView()->getTemplate()->getTemplateSet();
		if (count($tpl_set->getAuthorizedCollections()) == 1) {
			return false;
		}
		return '<div class="dmCheckAll">
				<a class="dmCheckAll">Check All</a> |
				<a class="dmUncheckAll">Uncheck All</a>
			</div>';
	}

	private function getCollectionListElements() {
		$tpl_set = $this->getView()->getTemplate()->getTemplateSet();
		if (count($tpl_set->getAuthorizedCollections()) == 1) {
			return false;
		}
		$collection_list = "";
		foreach (DMCollection::getAuthorized() as $c) {
			if (count($tpl_set->getAuthorizedCollections()) > 1
					&& !in_array($c, $tpl_set->getAuthorizedCollections())) {
				continue;
			}

			$input = DMHTTPRequest::getCurrent()->getSession()->getSearchInput();
			$checked = false;
			if ($input instanceof DMInput) {
				if (in_array($c->getAlias(), $input->getCollections())) {
					$checked = true;
				}
			} else {
				if ($this->getView()->getCollection()
						&& $this->getView()->getCollection()->getAlias()
						!= "/dmdefault") {
					$checked = ($c->equals($this->getView()->getCollection()));
				} else {
					$checked = true;
				}
			}
			$checked = $checked ? 'checked="checked"' : null;
			$collection_list .= sprintf(
				'<li>
					<label>
						<input type="checkbox" name="CISOROOT" value="%s" %s>
						%s
					</label>
				</li>',
				DMString::websafe($c->getAlias()),
				$checked,
				DMString::websafe($c->getName())
			);
			$checked = '';
		}
		return $collection_list;
	}

	private function getFieldOptionElements($selected = null) {
		$field_options = "";
		foreach ($this->getView()->getCollection()->getFields() as $f) {
			if (!$f->isSearchable()) {
				continue;
			}
			// disallow field searches for date; this won't affect date searches
			if ($f->getNick() == "date") {
				continue;
			}
			$field_options .= sprintf('<option value="%s"%s>%s</option>',
				DMString::paranoid($f->getNick()),
				($f->getNick() == $selected) ? ' selected="selected"' : '',
				DMString::websafe($f->getName()));
		}
		return $field_options;
	}

	private function getHiddenCollectionElement() {
		$allowed_collections = $this->getView()->getTemplate()
				->getTemplateSet()->getAuthorizedCollections();
		if (sizeof($allowed_collections) <> 1) {
			return "";
		}
		$elem = sprintf('<input type="hidden" name="CISOROOT" value="%s">',
			DMString::paranoid($allowed_collections[0], array('/')));
		return $elem;
	}

	private function getHiddenElements(array $get_parameters) {
		$hidden_elements = "";
		foreach ($get_parameters as $key => $value) {
			$hidden_elements .= sprintf(
					'<input type="hidden" name="%s" value="%s">',
					DMString::websafe($key),
					DMString::websafe($value));
		}
		return $hidden_elements;
	}

}
